import React, { Component } from 'react';
import Status from '../components/status';
import LatestResult from '../detection-detail/components/latest-result';
import AllAlive from '../detection-detail/components/all-alive';
import IpAliveList from '../detection-detail/components/ip-alive';
import PropTypes from 'prop-types';
import OneDayTable from '../components/oneday-table';
import { getZoomeyeIps, getOnedayTaskIpList, getTaskHistory, getVulDetectionTask } from '@api/task';
import { Breadcrumb, Tabs, Select } from 'antd';
import { withRouter } from 'react-router';
import { Link } from 'react-router-dom';
import _ from 'lodash';
import { connect } from 'react-redux';
import { FINISHED_TASK_STATES, PROCESSING_TASK_STATES, TASK_COMPARE_TYPES } from '@util/constants';
import './index.less';
import TaskInfo from './components/task-info';
import { actions as systemActions } from '@redux/reducer/system';
import { bindActionCreators } from 'redux';

const { TabPane } = Tabs;

class DetectionDetail extends Component {
  static defaultState = {
    task: {},
    ips: [],
    latestThreeResult: [],

    onedayList: [],
    vulTimes: [],
    statics: {},
    page: 1,
    pageSize: 10,
    currentVulTime: '',
    total: 0,

    currentAlive: 0,
    historyAlive: 0,

    ipsCount: 0,
    allPortCount: 0,
    sideBar: {},
    ipTimeline: null,
    ipsTaskFilter: {},
    ipsTableFilter: {
      page: 1,
      pageSize: 10
    },
    ipsTableSearch: '',
    ipsSiderFilter: {},
    locationFilter: {},
    loadingIps: false,
    isAbnormal: false,
    updatedTaskTarget: false,
    activeTabKey: 'vulList',
    roundId: ''
  };

  constructor(props) {
    super(props);
    this.state = DetectionDetail.defaultState;
    this.taskId = props.match.params.id;
  }

  componentDidMount() {
    getTaskHistory(this.taskId).then(res => {
      const vulTimes = [].concat(_.get(res, 'data.data.list', []));
      const currentVulTime = _.get(vulTimes[0], 'lastEnd');
      const roundId = _.get(vulTimes[0], '_id');
      this.setState(
        {
          vulTimes,
          currentVulTime,
          roundId
        },
        () => {
          this.loadDetail(() => {
            this.loadIps();
            this.loadOnedayList();
          });
          this.bindSocketIO();
        }
      );
    });
  }

  // eslint-disable-next-line
  UNSAFE_componentWillReceiveProps(nextProps) {
    let newTaskId = nextProps.match.params.id;
    if (newTaskId !== this.taskId) {
      this.taskId = newTaskId;
      this.setState(
        _.cloneDeep(DetectionDetail.defaultState),
        this.loadDetail(() => {
          this.loadIps();
          this.loadOnedayList();
        })
      );
    }
  }

  componentWillUnmount() {
    this.unbindSocketIO();
  }

  hitTaskFilter = data => {
    // eslint-disable-next-line
    const { taskId } = data;
    return taskId === this.taskId;
  };

  bindSocketIO = () => {
    const { socketIO } = this.props;
    if (!socketIO) {
      return;
    }
    socketIO.on('task_handler', this.onSocketIOData, this.hitTaskFilter);
  };

  unbindSocketIO = () => {
    const { socketIO } = this.props;
    if (!socketIO) {
      return;
    }
    socketIO.cancel('task_handler', this.onSocketIOData);
  };

  onSocketIOData = (data, method) => {
    /* eslint-disable */
    switch (method) {
      case 'task_running':
      case 'task_stopped':
      case 'task_failed':
      case 'task_deleted':
      case 'task_finished':
        this.loadDetail(() => {
          this.loadIps();
          this.loadOnedayList();
        });
        break;

      case 'task_progress':
        this.onSocketIODataProcess(data);
        break;
      default:
        break;
    }
    /* eslint-enable */
  };

  onSocketIODataProcess = data => {
    const { progress } = data;
    const task = _.clone(this.state.task);
    task.progress = progress;
    this.loadDetail(() => {
      this.loadIps();
      this.loadOnedayList();
    });
    this.setState({ task });
  };

  loadDetail(callback) {
    getVulDetectionTask(this.taskId).then(res => {
      const task = _.get(res, 'data.data.task', {});
      task.params = _.get(task, 'maxDetectionTaskParams', {});
      const historical = Number(_.get(res, 'data.data.historical', 0)) || 0;
      const allResults = _.get(res, 'data.data.recentThreeResult', []);
      task.count = _.get(task, 'times', '-');
      const currentAlive = Number(_.get(allResults, '[0].targets', 0)) || 0;

      const historyAlive = historical - currentAlive;
      const status = _.get(task, 'status');
      const isDeleted = _.get(task, 'isDeleted');
      // const roundId = _.get(task, '_id');

      let latestThreeResult;
      if (
        FINISHED_TASK_STATES.indexOf(status) !== -1 ||
        isDeleted ||
        PROCESSING_TASK_STATES.indexOf(status) !== -1
      ) {
        latestThreeResult = [allResults[2], allResults[1], allResults[0]].filter(Boolean);
      } else {
        latestThreeResult = [allResults[1], allResults[0], { _id: '等待开始...' }].filter(Boolean);
      }
      const ipsTaskFilter = {
        compare: ''
      };
      ipsTaskFilter.roundId = _.get(allResults[0], '_id');

      this.setState(
        {
          task,
          currentAlive,
          historyAlive,
          latestThreeResult,
          ipsTaskFilter
        },
        callback
      );
    });
  }

  loadIps() {
    const {
      ipsTaskFilter,
      ipsTableFilter,
      ipsSiderFilter,
      locationFilter,
      ipsTableSearch,
      roundId
    } = this.state;
    this.setState({ loadingIps: true });
    getZoomeyeIps(
      _.pickBy(
        {
          // eslint-disable-next-line
          taskId: this.taskId,
          ...ipsTaskFilter,
          ...ipsTableFilter,
          ...ipsSiderFilter,
          search: ipsTableSearch,
          roundId,
          ..._.pickBy(_.pick(locationFilter, ['country', 'region', 'city']), Boolean)
        },
        Boolean
      )
    )
      .then(res => {
        const ips = _.get(res, 'data.data.list', []);
        const sideBar = _.get(res, 'data.data.side_bar', {});
        let currentLocationBar = _.get(sideBar, 'location_bar'),
          lastLocationBar = currentLocationBar,
          maxIter = 10;
        while (_.get(currentLocationBar, 'length') === 1 && maxIter--) {
          lastLocationBar = currentLocationBar;
          currentLocationBar = _.get(currentLocationBar, '0.children', []);
        }
        if (!_.get(currentLocationBar, 'length')) {
          currentLocationBar = lastLocationBar;
        }
        _.set(sideBar, 'location_bar', currentLocationBar);
        const ipsCount = _.get(res, 'data.data.count', 0);
        const allPortCount = _.get(res, 'data.data.allPortCount', 0);

        const isAbnormal = _.get(res, 'data.data.isAbnormal', false);
        this.setState({ ips, sideBar, ipsCount, isAbnormal, allPortCount });
      })
      .finally(() => {
        this.setState({ loadingIps: false });
      });
  }

  loadOnedayList = () => {
    const { page, pageSize, roundId } = this.state;
    if (!roundId || !page || !pageSize) {
      return;
    }
    // eslint-disable-next-line
    getOnedayTaskIpList({ task_id: this.taskId, page, pageSize, roundId }).then(res => {
      const { list = [], statics = {}, count = 0 } = _.get(res, 'data.data', {});
      this.setState({ onedayList: list, statics, total: count, expandedRowKeys: [] });
    });
  };

  onCurrentTimeChange = (currentVulTime, current) => {
    this.setState(
      {
        currentVulTime: currentVulTime,
        roundId: _.get(current, 'key'),
        page: 1,
        pageSize: 10
      },
      () => {
        this.loadOnedayList();
        this.loadIps();
      }
    );
  };

  onIpsTableChange = (page, pageSize) => {
    this.setState(
      {
        ipsTableFilter: { page, pageSize }
      },
      this.loadIps
    );
  };

  onIpsTableSearchChange = value => {
    this.setState({ ipsTableSearch: value }, () => this.loadIps());
  };

  onClickLatest = ({ selectedSeriesIndex, selectedDataIndex }) => {
    const { latestThreeResult } = this.state;
    const compare = TASK_COMPARE_TYPES[selectedSeriesIndex - 1] || '';
    const roundId = _.get(latestThreeResult, `[${selectedDataIndex}]._id`);
    const created = _.get(latestThreeResult, `[${selectedDataIndex}].created`);
    this.setState(
      {
        ipsTableFilter: {
          page: 1,
          pageSize: 10
        },
        ipsTaskFilter: {
          compare
        },
        roundId,
        currentVulTime: created,
        activeTabKey: selectedSeriesIndex === 3 ? 'vulList' : 'ipList'
      },
      () => {
        this.loadIps();
        this.loadOnedayList();
      }
    );
  };

  onClickAll = () => {
    this.setState(
      {
        ipsTableFilter: {
          page: 1,
          pageSize: 10
        },
        ipsTaskFilter: {
          compare: TASK_COMPARE_TYPES[2]
        },
        activeTabKey: 'ipList'
      },
      () => {
        this.loadIps();
        this.loadOnedayList();
      }
    );
  };

  updateTaskTargetTarget = (taskTarget = {}) => {
    this.setState({ task: Object.assign(this.state.task, taskTarget), updatedTaskTarget: true });
  };

  onBottomTabsChange = key => {
    this.setState({ activeTabKey: key });
  };

  onTableChange = ({ current: page, pageSize }) => {
    this.setState(
      {
        page,
        pageSize
      },
      this.loadOnedayList
    );
  };

  render() {
    const {
      task = {},
      currentAlive,
      historyAlive,
      latestThreeResult,
      ipsTaskFilter,
      activeTabKey,
      ips,
      ipsCount,
      allPortCount,
      ipsTableFilter,
      ipsTableSearch,
      loadingIps,
      onedayList,
      page,
      pageSize,
      total,
      currentVulTime,
      statics,
      vulTimes
    } = this.state;
    const pagination = {
      current: page,
      pageSize,
      total,
      showTotal: num => `共 ${num} 条`,
      showQuickJumper: true,
      showSizeChanger: true
    };
    const isDetecting = task.status === 'processing';
    return (
      <div className="task-manage-detection-detail">
        <div className="bread">
          <Breadcrumb>
            <Breadcrumb.Item>
              <Link to="/task-manage">任务管理</Link>
            </Breadcrumb.Item>
            <Breadcrumb.Item>
              <span style={{ fontWeight: 600 }}>任务详情</span>
            </Breadcrumb.Item>
          </Breadcrumb>
        </div>
        <div className="tmz-top">
          <div className="left">
            <Status task={task} className="status" />
            <TaskInfo task={task} />
          </div>
        </div>
        <div className="tmz-middle">
          <div className="left">
            <div className="title">近三轮检测结果</div>
            <div className="latest-result">
              <LatestResult
                data={latestThreeResult}
                filter={ipsTaskFilter}
                onClick={this.onClickLatest}
                scanType={task.scanType}
              />
            </div>
          </div>

          <div className="right">
            <div className="title">累计存活目标</div>
            <div className="all-alive">
              <AllAlive
                isDetecting={isDetecting}
                allCount={currentAlive + historyAlive}
                onClick={this.onClickAll}
              />
            </div>
          </div>
        </div>

        <div className="tmz-bottom-tabs">
          <Tabs
            activeKey={activeTabKey}
            onChange={this.onBottomTabsChange}
            tabBarExtraContent={
              <div>
                <span className="label">时间</span>
                &nbsp;&nbsp;
                <Select
                  value={currentVulTime}
                  className="select"
                  onChange={this.onCurrentTimeChange}
                >
                  {vulTimes.map(vt => (
                    <Select.Option value={_.get(vt, 'lastEnd')} key={_.get(vt, '_id')}>
                      {_.get(vt, 'lastEnd')}
                    </Select.Option>
                  ))}
                </Select>
              </div>
            }
          >
            <TabPane tab="漏洞扫描结果" key="vulList">
              <div className="tmo-result__info">
                {currentVulTime} 扫描到漏洞：一共{_.get(statics, 'total', 0)}个漏洞,其中严重
                {_.get(statics, 'fatal', 0)}个,高危{_.get(statics, 'high', 0)}个，中危
                {_.get(statics, 'middle', 0)}个，低危{_.get(statics, 'low', 0)}个。
              </div>
              <div className="tmo-result__table">
                <OneDayTable
                  onedayList={onedayList}
                  pagination={pagination}
                  onTableChange={this.onTableChange}
                />
              </div>
            </TabPane>
            <TabPane tab="存活目标列表" key="ipList">
              <IpAliveList
                ips={ips}
                ipsCount={ipsCount}
                allPortCount={allPortCount}
                onIpsTableChange={this.onIpsTableChange}
                ipsTableFilter={ipsTableFilter}
                ipsTaskFilter={ipsTaskFilter}
                ipsTableSearch={ipsTableSearch}
                onIpsTableSearchChange={this.onIpsTableSearchChange}
                loading={loadingIps}
                timeline={currentVulTime}
                isDetecting={isDetecting}
                scanType={task.scanType}
              />
            </TabPane>
          </Tabs>
        </div>
      </div>
    );
  }
}

DetectionDetail.propTypes = {
  history: PropTypes.object,
  match: PropTypes.object,
  socketIO: PropTypes.object
};

const mapStateToProps = state => {
  return {
    socketIO: _.get(state, 'socketIO.socketIO', null)
  };
};

const mapDispatchToProps = dispatch => {
  return {
    ...bindActionCreators(systemActions, dispatch)
  };
};

export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(DetectionDetail)
);
